import warnings
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.linear_model.coordinate_descent import ConvergenceWarning
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression,LassoCV,RidgeCV,ElasticNetCV

# 设置字符集，防止中文乱码
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False

# 拦截异常
warnings.filterwarnings(action='ignore',category=UserWarning)
warnings.filterwarnings(action='ignore',category=ConvergenceWarning)

## 自变量名称
columns_x = ["fixed acidity","volatile acidity","citric acid",
         "residual sugar","chlorides","free sulfur dioxide",
         "total sulfur dioxide","density","pH","sulphates",
         "alcohol", "type"]

## 因变量名称
columns_y = "quality"

def run():
    # 读取数据
    path_1 = '../data/winequality-red.csv'
    df_1 = pd.read_csv(path_1, sep=';')
    df_1['type'] = 1  # 设置数据类型为红葡萄酒

    path_2 = '../data/winequality-white.csv'
    df_2 = pd.read_csv(path_2, sep=';')
    df_2['type'] = 2  # 设置数据类型为白葡萄酒

    # 合并两个df
    df_3 = pd.concat([df_1, df_2], axis=0)

    # 异常数据处理
    df_4 = df_3.replace('?', np.nan)
    datas = df_4.dropna(how='any')  # 只要有列为空，就进行删除操作
    X=datas[columns_x]
    Y=datas[columns_y]

    # 创建模型列表
    models=[
        Pipeline([
            ('Poly',PolynomialFeatures()),
            ('Linear',LinearRegression())
        ]),
        Pipeline([
            ('Poly',PolynomialFeatures()),
            ('Linear',RidgeCV(alphas=np.logspace(-4,2,20)))
        ]),
       Pipeline([
           ('Poly',PolynomialFeatures()),
           ('Linear',LassoCV(alphas=np.logspace(-4,2,20)))
       ]),
       Pipeline([
           ('Poly',PolynomialFeatures()),
           ('Linear',ElasticNetCV(alphas=np.logspace(-4,2,20),l1_ratio=np.linspace(0,5,1)))
       ])
   ]

    # 将数据分为训练数据和测试数据
    X_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=0.01,random_state=0)
    k=range(len(X_test))

    # 给定阶以及颜色
    d_pool=np.arange(1,4,1)
    m=len(d_pool)
    clrs=[]
    for c in np.linspace(5570560,255,m):
       clrs.append('#%06x' % int(c))

    titles=u"线性回归预测",u"Ridge回归预测",u"Lasso回归预测",u"ElasticNet预测"
    plt.figure(figsize=(16,8),facecolor='w')

    for t in range(4):
       plt.subplot(2,2,t+1)
       model=models[t]
       plt.plot(k,Y_test,c='r',lw=2,alpha=0.75,zorder=10,label=u'真实值')
       for i,d in enumerate(d_pool):
           # 设置参数
           model.set_params(Poly__degree=d)
           # 模型训练
           model.fit(X_train,Y_train)
           # 模型预测及计算R^2
           Y_predict=model.predict(X_test)
           R=model.score(X_train,Y_train)
           # 输出信息
           lin=model.get_params('Linear')['Linear']
           output = u"%s:%d阶, 截距:%d, 系数:" %(titles[t],d,lin.intercept_)
           print(output,lin.coef_)
           # 图形展示
           plt.plot(k,Y_predict,c=clrs[i],lw=2,alpha=0.75,zorder=i,label=u'%d阶预测值,R^2=%.3f' % (d,R))
       plt.legend(loc='upper left')
       plt.grid(b=True)
       plt.title(titles[t],fontsize=18)
       plt.xlabel('X',fontsize=16)
       plt.ylabel('Y',fontsize=16)
    plt.suptitle(u'葡萄酒质量预测',fontsize=22)
    plt.show()


run()